package com.yanqu.road.dao.impl.player;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dao.impl.TempDao;
import com.yanqu.road.dao.impl.logic.ResultSetParseEntityManger;
import com.yanqu.road.entity.estatewar.EstateFloorInfo;
import com.yanqu.road.entity.estatewar.UserEstateFloor;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.player.UserPatrons;
import com.yanqu.road.entity.player.UserPatronsSkill;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UserEstateFloorDaoImpl extends TempDao {

    public Map<Integer, Map<Integer, UserEstateFloor>> getUserEstateFloorMap() {
        Map<Integer, Map<Integer, UserEstateFloor>> dataMap = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;

        {
            List<UserEstateFloor> dataList = new ArrayList<>();
            String sql = "SELECT * FROM t_u_estate";
            try {
                getDb().setConnName(DbNameStrategy.getUserDb());
                call = getDb().getConnection().prepareCall(sql);
                rs = call.executeQuery();
                while (rs.next()) {
                    UserEstateFloor data = initUserEstateFloor(rs);
                    dataList.add(data);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                getDb().closeConnection(call, rs);
            }

            for (UserEstateFloor data : dataList) {
                Map<Integer, UserPatrons> userPatronsMap = new UserPatronsDaoImpl().getUserPatronsMap(data.getUserId());
                Map<Integer, List<UserPatronsSkill>> skillMap = new UserPatronsSkillDaoImpl().getUserPatronsSkillMap(data.getUserId());
                for (Map.Entry<Integer, List<UserPatronsSkill>> skillEntry : skillMap.entrySet()) {
                    if (userPatronsMap.containsKey(skillEntry.getKey())) {
                        userPatronsMap.get(skillEntry.getKey()).setSkillList(skillEntry.getValue());
                    }
                }
                data.setPatronsList(new ArrayList<>(userPatronsMap.values()));

                if(!dataMap.containsKey(data.getType())){
                    dataMap.put(data.getType(), new ConcurrentHashMap<>());
                }
                if(!dataMap.get(data.getType()).containsKey(data.getPos())) {
                    dataMap.get(data.getType()).put(data.getPos(), data);
                }
            }
        }

//        {
//            String sql = "SELECT * FROM t_u_estate t1 LEFT JOIN t_u_patrons t2 on t1.userId = t2.userId LEFT JOIN t_u_patrons_skill t3 on t1.userId = t3.userId AND " +
//                    "t2.patronsId = t3.patronsId";
//            try {
//                getDb().setConnName(DbNameStrategy.getUserDb());
//                call = getDb().getConnection().prepareCall(sql);
//                rs = call.executeQuery();
//                while (rs.next()) {
//                    UserEstateFloor data = initUserEstateFloor(rs);
//                    if(!dataMap.containsKey(data.getType())){
//                        dataMap.put(data.getType(), new ConcurrentHashMap<>());
//                    }
//                    if(!dataMap.get(data.getType()).containsKey(data.getPos())) {
//                        dataMap.get(data.getType()).put(data.getPos(), data);
//                    }
//                    if(rs.getInt("patronsId") > 0){
//                        data = dataMap.get(data.getType()).get(data.getPos());
//                        UserPatrons userPatrons = ResultSetParseEntityManger.initUserPatrons(rs);
//                        if(!data.isContainsPatrons(userPatrons.getPatronsId())){
//                            data.addPatrons(userPatrons);
//                        }
//                        if(rs.getInt("skillId") > 0) {
//                            userPatrons = data.getPatrons(userPatrons.getPatronsId());
//                            UserPatronsSkill userPatronsSkill = ResultSetParseEntityManger.initUserPatronsSkill(rs);
//                            if(!userPatrons.isContainsSkill(userPatronsSkill.getType(), userPatronsSkill.getSkillId())){
//                                userPatrons.addSkill(userPatronsSkill);
//                            }
//                        }
//                    }
//                }
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            } finally {
//                getDb().closeConnection(call, rs);
//            }
//        }

        return dataMap;
    }

    public boolean initUserEstateFloorMap(Map<Integer, EstateFloorInfo> estateFloorInfoMap, Map<Integer, UserEstateFloor> userEstateFloorMap) {
        boolean result = false;
        String sql = "INSERT INTO t_u_estate(type,pos,userId,userBaseInfo,joinTime,totalAbility) VALUES(?,?,?,?,?,?)";
        getDb().setConnName(DbNameStrategy.getUserDb());
        List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
        for (EstateFloorInfo estateFloor : estateFloorInfoMap.values()) {
            if (!userEstateFloorMap.containsKey(estateFloor.getPos())) {
                Map<Integer, DbParameter> para = new HashMap<>();
                int i = 1;
                para.put(i++, new DbParameter(Types.INTEGER, estateFloor.getType()));
                para.put(i++, new DbParameter(Types.INTEGER, estateFloor.getPos()));
                para.put(i++, new DbParameter(Types.BIGINT, 0L));
                UserBaseInfo userBaseInfo = new UserBaseInfo();
                para.put(i++, new DbParameter(Types.VARCHAR, JSON.toJSONString(userBaseInfo)));
                para.put(i++, new DbParameter(Types.BIGINT, 0L));
                para.put(i++, new DbParameter(Types.VARCHAR, "0"));
                mapList.add(para);
            }
        }
        if (getDb().executeBatchQuery(sql, mapList) > -1) {
            result = true;
        }
        return result;
    }

    public boolean updateUserEstateFloorList(List<UserEstateFloor> userEstateFloorList) {
        boolean result = false;
        String sql = "UPDATE t_u_estate SET userId=?,joinTime=?,totalAbility=?,userBaseInfo=? WHERE type=? and pos=?";
        getDb().setConnName(DbNameStrategy.getUserDb());
        List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
        for (UserEstateFloor userEstateFloor : userEstateFloorList) {
            Map<Integer, DbParameter> para = new HashMap<>();
            int i = 1;
            para.put(i++, new DbParameter(Types.BIGINT, userEstateFloor.getUserId()));
            para.put(i++, new DbParameter(Types.BIGINT, userEstateFloor.getJoinTime()));
            para.put(i++, new DbParameter(Types.VARCHAR, userEstateFloor.getTotalAbility().toString()));
            para.put(i++, new DbParameter(Types.VARCHAR, userEstateFloor.getUserBaseInfoJsonStr()));
            para.put(i++, new DbParameter(Types.INTEGER, userEstateFloor.getType()));
            para.put(i++, new DbParameter(Types.INTEGER, userEstateFloor.getPos()));
            mapList.add(para);
        }
        if (getDb().executeBatchQuery(sql, mapList) > -1) {
            result = true;
        }
        return result;
    }

    private UserEstateFloor initUserEstateFloor(ResultSet rs) throws SQLException {
        UserEstateFloor data = new UserEstateFloor();
        data.setType(rs.getInt("type"));
        data.setPos(rs.getInt("pos"));
        data.setUserId(rs.getLong("userId"));
        data.setJoinTime(rs.getLong("joinTime"));
        String totalAbilityStr = rs.getString("totalAbility");
        BigInteger totalAbility = BigInteger.ZERO;
        if(!StringUtils.isNullOrEmpty(totalAbilityStr)){
            totalAbility = new BigInteger(totalAbilityStr);
        }
        String baseUserInfoStr = rs.getString("userBaseInfo");
        if(null == baseUserInfoStr){
            baseUserInfoStr = "";
        }
        UserBaseInfo userBaseInfo = JSON.parseObject(baseUserInfoStr, new TypeReference<UserBaseInfo>() {});
        if(null != userBaseInfo) {
            data.setUserBaseInfo(userBaseInfo);
        }
        data.setTotalAbility(totalAbility);
        return data;
    }
}
